home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 27.6 KB | 1,142 lines | [TEXT/MPS ] |
- // UMenuMgr.cp
- // Copyright © 1984-1991 by Apple Computer Inc. All rights reserved.
-
- #ifndef __UMENUMGR__
- #include <UMenuMgr.h>
- #endif
-
- #ifndef __STDIO__
- #include <StdIo.h>
- #endif
-
- #ifndef __GEOMETRY__
- #include <Geometry.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __UOBJECT__
- #include <UObject.h>
- #endif
-
- #ifndef __UFAILURE__
- #include <UFailure.h>
- #endif
-
- #ifndef __ULIST__
- #include <UList.h>
- #endif
-
- #ifndef __UPATCH__
- #include <UPatch.h>
- #endif
-
- #ifndef __UMEMORY__
- #include <UMemory.h>
- #endif
-
- #ifndef __TEXTEDIT__
- #include <Textedit.h>
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include <UMacAppUtilities.h>
- #endif
-
- #ifndef __UMACAPPGLOBALS__
- #include <UMacAppGlobals.h>
- #endif
-
- #ifndef __TRAPS__
- #include <Traps.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __UITERATOR__
- #include <UIterator.h>
- #endif
-
- #define kHierarchical TRUE
- #define kNotHierarchical !kHierarchical
-
- #define kDoHierarchical TRUE
- #define kDontDoHierarchical !kDoHierarchical
-
- typedef struct MenuCmdRecord
- {
- CmdNumber theCmdNumber;
- short theMenuNumber;
- short theItemNumber;
- } *MenuCmdRecordPtr, ** MenuCmdRecordHandle;
-
- class TCmdTable : public TSortedDynamicArray
- {
- public:
- virtual pascal void ICmdTable(void);
- virtual pascal CompareResult CompareElements(void* Element1,
- void* Element2);// override
- virtual pascal void CmdToMenuItem(CmdNumber theCommand,
- short& menu,
- short& item);
- virtual pascal CmdNumber CmdFromMenuItem(short menu,
- short item);
- /* Given a menuID,item # return the appropriate command number. if there
- is no such command number, return -BOR(((menu) << 8), item). If the
- item number is <0 then assume that it is a negative command number. */
- virtual pascal void AddToTable(CmdNumber commandNumber,
- short menuNumber,
- short itemNumber);
- };
-
-
- class TMenuTable : public THandleList
- {
- public:
- virtual pascal void IMenuTable(void);
- virtual pascal MenuHandle GetMenu(short menuID);
- virtual pascal CompareResult Compare(Handle item1,
- Handle item2);// override
- };
-
-
- Handle pHNullMenuProc; // Handle to null menu proc
-
- TCmdTable* gCmdTable; /* command numbers and their associated menu
- and item numbers */
- TMenuTable* gMenuTable; // list of menus created/managed by MacApp
-
- pascal void NullMenuProc(short message,
- MenuHandle aMenuHandle,
- Rect& menuRect,
- Point hitPt,
- short& whichItem);
-
- //--------------------------------------------------------------------------------------------------
- Boolean gMenusAreInvalid;
- Boolean gMenuBarIsInvalid;
-
- #if qDebug
- Boolean gTraceSetupMenus;
- #endif
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- pascal void TCmdTable::ICmdTable(void)
-
- {
- this->ISortedDynamicArray(0, sizeof(MenuCmdRecord));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal CompareResult TCmdTable::CompareElements(void* Element1,
- void* Element2)// override
-
- {
- CmdNumber theCommanditem1 = ((MenuCmdRecordPtr)Element1)->theCmdNumber;
- CmdNumber theCommanditem2 = ((MenuCmdRecordPtr)Element2)->theCmdNumber;
-
- if (theCommanditem1 > theCommanditem2)
- return kItem1GreaterThanItem2;
- else if (theCommanditem1 < theCommanditem2)
- return kItem1LessThanItem2;
- else
- return kItem1EqualItem2;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- // A local class to pass in to the search routine as a comparison function
- class CCmdToMenuItem
- {
- // Fields
-
- CmdNumber& theCommand;
- TCmdTable* theCmdTable;
-
- public:
-
- // Constructor
-
- CCmdToMenuItem(CmdNumber& aCommand,
- TCmdTable* aCmdTable) :
- theCommand(aCommand),
- theCmdTable(aCmdTable)
- {
- }
-
- // Method
-
- pascal CompareResult TestItem(ArrayIndex anItem);
- };
-
- #pragma segment MAMenuRes
- pascal CompareResult CCmdToMenuItem::TestItem(ArrayIndex anItem)
- {
- CmdNumber theCommanditem;
-
- theCommanditem = ((MenuCmdRecordPtr)theCmdTable->ComputeAddress(anItem))->theCmdNumber;
-
- if (theCommanditem > theCommand)
- return kItemGreaterThanCriteria;
- else if (theCommanditem < theCommand)
- return kItemLessThanCriteria;
- else
- return kItemEqualCriteria;
- }
-
- typedef pascal CompareResult(* TestItem)(ArrayIndex anItem,
- void* staticLink);
-
- #pragma segment MAMenuRes
- pascal void TCmdTable::CmdToMenuItem(CmdNumber theCommand,
- short& menu,
- short& item)
-
- {
- ArrayIndex index = 0;
- CCmdToMenuItem aCCmdToMenuItem(theCommand, this);
-
- if (theCommand < 0) /* negative commands are mapped not table
- based */
- {
- menu = (short)((-theCommand) >> 8);
- item = (short)((-theCommand) & 255);
- }
- else
- {
- if (this->DoSearchElement((TestItem) & CCmdToMenuItem::TestItem, &aCCmdToMenuItem, index))
- {
- MenuCmdRecordPtr aMenuCmdRecordPtr = (MenuCmdRecordPtr)ComputeAddress(index);
- menu = aMenuCmdRecordPtr->theMenuNumber;
- item = aMenuCmdRecordPtr->theItemNumber;
- }
- else // not found
- {
- menu = 0;
- item = 0;
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal CmdNumber TCmdTable::CmdFromMenuItem(short menu,
- short item)
- /* Given a menuID/item # return the appropriate command number. if there
- is no such command number, return -BOR(((menu) << 8), item). If the
- item number is <0 then assume that it is a negative command number. */
-
- {
- if (item < 0)
- return -item;
- else
- {
- if (item > 0)
- {
-
- // Search the table linearly.
- for (ArrayIndex i = 1; i <= this->GetSize(); ++i)
- {
- MenuCmdRecordPtr aMenuCmdRecordPtr = (MenuCmdRecordPtr)this->ComputeAddress(i);
- if ((menu == aMenuCmdRecordPtr->theMenuNumber) && (item == aMenuCmdRecordPtr->theItemNumber))
- {
- return aMenuCmdRecordPtr->theCmdNumber;
- }
- }
- }
-
- #if qDebugMsg
- if ((menu > 127) || (item > 255))
- {
- fprintf(stderr, "menu : %1d , item : %1d \n", menu, item);
- fprintf(stderr, "Menu/item number is too big for a negative command number!");
- ProgramBreak("Try using a negative item number instead.");
- }
- #endif
-
- return -((menu << 8) | item);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- pascal void TCmdTable::AddToTable(CmdNumber commandNumber,
- short menuNumber,
- short itemNumber)
-
- {
- MenuCmdRecord arec;
-
-
- if (commandNumber > 0) // Negative numbers are mapped not tabled
- {
- arec.theCmdNumber = commandNumber;
- arec.theMenuNumber = menuNumber;
- arec.theItemNumber = itemNumber;
-
- this->InsertElementInOrder((Ptr) & arec);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- pascal void TMenuTable::IMenuTable(void)
-
- {
- this->IHandleList();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- // A local class to pass in to the search routine as a comparison function
- class CGetMenu
- {
- // Fields
-
- short& menuID;
-
- public:
-
- // Constructor
-
- CGetMenu(short& amenuID) :
- menuID(amenuID)
- {
- }
-
- // Method
-
- pascal CompareResult TestItem(Handle anItem);
- };
-
- #pragma segment MAMenuRes
- pascal CompareResult CGetMenu::TestItem(Handle anItem)
- {
- short menuIDitem = (*((MenuHandle)anItem))->menuID;
-
- if (menuIDitem > menuID)
- return kItemGreaterThanCriteria;
- else if (menuIDitem < menuID)
- return kItemLessThanCriteria;
- else
- return kItemEqualCriteria;
- }
-
-
- typedef pascal CompareResult(* GetMenuTestItem)(Handle anItem,
- void* staticLink);
-
- #pragma segment MAMenuRes
- pascal MenuHandle TMenuTable::GetMenu(short menuID)
-
- {
- ArrayIndex index;
- CGetMenu aCGetMenu(menuID);
-
- return ((MenuHandle)this->DoSearch((GetMenuTestItem) & CGetMenu::TestItem, &aCGetMenu, index)); // discard index
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal CompareResult TMenuTable::Compare(Handle item1,
- Handle item2)// override
-
- {
- short menuID1 = (*((MenuHandle)item1))->menuID;
- short menuID2 = (*((MenuHandle)item2))->menuID;
-
- if (menuID1 > menuID2)
- return kItem1GreaterThanItem2;
- else if (menuID1 < menuID2)
- return kItem1LessThanItem2;
- else
- return kItem1EqualItem2;
- }
-
- //--------------------------------------------------------------------------------------------------
- #if qDebugMsg
- #pragma segment MADebug
-
- char TraceMenuName(CmdNumber aCmd)
- // For debugging purposes only--used to dump the name and number of a command
-
- {
- Str255 cmdName;
-
- CmdToName(aCmd, cmdName);
- fprintf(stderr, " %1d [%s],", aCmd, (char *) cmdName);
- return ' ';
- }
- #endif
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void InvalidateMenus(void)
-
- {
- gMenusAreInvalid = TRUE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- struct MenuBarRecord
- {
- short nMenus;
- short menuID[1000];
- };
-
-
- typedef MenuBarRecord* MenuBarPtr, ** MenuBarHandle;
-
- pascal void AddMenuBar(short itsID,
- Boolean isHierarchical)
-
- {
- short hier;
- MenuBarHandle hmbar;
-
-
- if (isHierarchical)
- hier = -1;
- else
- hier = 0;
-
- hmbar = (MenuBarHandle)GetResource('MBAR', itsID);
- if (hmbar)
- {
- for (short i = 0; i <= (*hmbar)->nMenus; ++i)
- {
- MenuHandle aMenu = MAGetMenu((*hmbar)->menuID[i]);
- if (aMenu)
- MAInsertMenu(aMenu, hier);
- }
- ReleaseResource((Handle)hmbar);
- // hmbar = NULL;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void ValidateMenus(void)
-
- {
- gMenusAreInvalid = FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal Boolean MenusHavePendingUpdate(void)
-
- {
- return gMenusAreInvalid;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void InvalidateMenuBar(void)
- {
- InvalidateMenus(); /* if the menubar is invalidated then the
- menu items must be also */
-
- /* On systems that have invalidate menu bar use that functionality instead of setting the global.
- The system will redraw the menu bar at the next convenient time. */
- if (TrapExists(_InvalMenuBar))
- {
- InvalMenuBar();
- gMenuBarIsInvalid = FALSE; /* don't track in the application when using
- the trap */
- }
- else
- gMenuBarIsInvalid = TRUE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void ValidateMenuBar(void)
-
- {
- gMenuBarIsInvalid = FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal Boolean MenuBarHasPendingUpdate()
-
- {
- return gMenuBarIsInvalid;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal Boolean CmdEnabled(CmdNumber cmd)
-
- {
- short menuNo;
- short itemNo;
- MenuHandle theMenu;
-
- theMenu = CmdToComponents(cmd, menuNo, itemNo);
-
- if (theMenu)
- if ((itemNo > 0) && (itemNo < 32))
- return (((*theMenu)->enableFlags >> itemNo) != 0);
- else
- return TRUE;
- else
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal CmdNumber CmdFromMenuItem(short menu,
- short item)
-
- {
- return gCmdTable->CmdFromMenuItem(menu, item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void CmdToMenuItem(CmdNumber aCmd,
- short& menu,
- short& item)
-
- {
- gCmdTable->CmdToMenuItem(aCmd, menu, item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void CmdToName(CmdNumber aCmd,
- Str255& menuText)
-
- {
- short anItem;
- short aMenu;
-
- menuText = "";
-
- MenuHandle mHandle = CmdToComponents(aCmd, aMenu, anItem);
- if (mHandle)
- GetItem(mHandle, anItem, menuText);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal MenuHandle CmdToComponents(CmdNumber cmd,
- short& menuNo,
- short& itemNo)
-
- {
- CmdToMenuItem(cmd, menuNo, itemNo);
- if (menuNo) // was found
- return MAGetMenu(menuNo);
- else
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- #pragma segment MAMenuRes
-
- // Calls DoToMenu for each menu in the menu bar, DoToMenu needs to be smart enough to
- // exclude hierarchical if desired.
- pascal void EachMenuDo(DoToMenuType DoToMenu,
- void* staticLink)
- {
- CHandleIterator iter(gMenuTable);
-
- for (MenuHandle item = (MenuHandle)iter.FirstHandle(); iter.More(); item = (MenuHandle)iter.NextHandle())
- if (GetMHandle((*(item))->menuID)) // if it's in the menulist
- DoToMenu(item, kHierarchical, staticLink);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void Enable(CmdNumber aCmd,
- Boolean canDo)
-
- {
- short menu;
- short item;
- MenuHandle aMenuHandle;
-
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... Enable(%c%s)", TraceMenuName(aCmd), gBoolString[canDo]);
- #endif
-
- aMenuHandle = CmdToComponents(aCmd, menu, item);
- if (aMenuHandle)
- if (canDo)
- EnableItem(aMenuHandle, item);
- else
- DisableItem(aMenuHandle, item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void EnableCheck(CmdNumber aCmd,
- Boolean canDo,
- Boolean checkIt)
-
- {
- short menu;
- short item;
- MenuHandle aMenuHandle;
-
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... EnableCheck(%c%s, %s)", TraceMenuName(aCmd), gBoolString[canDo], gBoolString[checkIt]);
- #endif
-
- aMenuHandle = CmdToComponents(aCmd, menu, item);
- if (aMenuHandle)
- {
- if (canDo)
- EnableItem(aMenuHandle, item);
- else
- DisableItem(aMenuHandle, item);
- CheckItem(aMenuHandle, item, checkIt);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void DoGetResMenu(void* staticLink)
-
- {
- short menuResID = *((short*)staticLink);
- *((MenuHandle *)staticLink) = (MenuHandle)GetResource('MENU', menuResID);
- }
-
-
- pascal MenuHandle GetResMenu(short menuResID)
- /* Allow us to get a menu when it's not available via GetMHandle.
- !!! Really should perform the other functions of GetMenu (load menuproc, color table, etc.*/
-
- {
- long staticLink = menuResID; // on entry to DoGetResMenu, staticLink is menuResID
-
- WithApplicationResFileDo(&DoGetResMenu, &staticLink);
-
- return (MenuHandle)staticLink; // on exit from DoGetResMenu, staticLink is MenuHandle
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TRes
-
- pascal MenuHandle ConvertToMenu(Handle CMNUHandle)
-
- {
- typedef CmdNumber* CmdNumberPtr;
-
- MenuHandle theMenuHandle = NULL;
- Ptr theCMNUPtr;
- Ptr theMENUPtr;
- short i;
- short menuNo;
- short itemNo;
- CmdNumber cmdNo;
- Ptr endPtr;
-
- theMenuHandle = (MenuHandle)NewPermHandle(GetHandleSize(CMNUHandle));
- LockHandleHigh(CMNUHandle);
- LockHandleHigh((Handle)theMenuHandle);
-
- theCMNUPtr = (Ptr)StripLong(*CMNUHandle);
- theMENUPtr = (Ptr)StripLong(*theMenuHandle);
- menuNo = *((IntegerPtr)theCMNUPtr);
-
- i = (*((Str255 *)(theCMNUPtr + 14))).Length() + 15;
- BlockMove(theCMNUPtr, theMENUPtr, i); // move menu header into MENU resource
- theCMNUPtr = (Ptr)(theCMNUPtr + i);
- theMENUPtr = (Ptr)(theMENUPtr + i);
- itemNo = 0;
- endPtr = (Ptr)(theCMNUPtr + GetHandleSize(CMNUHandle));
- while ((theCMNUPtr < endPtr) && (((*((Str255 *)theCMNUPtr)).Length()) != 0))
- {
- i = ((*((Str255 *)theCMNUPtr)).Length()) + 5;
- BlockMove(theCMNUPtr, theMENUPtr, i); // move menu item data sans command number
- theCMNUPtr = (Ptr)(theCMNUPtr + i);
- theMENUPtr = (Ptr)(theMENUPtr + i);
- if ((((long)theCMNUPtr) & 0x00000001) == 1)// word align
- theCMNUPtr = (Ptr)(theCMNUPtr + 1);
- cmdNo = *((CmdNumberPtr)theCMNUPtr);
- ++itemNo;
- theCMNUPtr = (Ptr) (theCMNUPtr + sizeof(CmdNumber));
-
- gCmdTable->AddToTable(cmdNo, menuNo, itemNo);
- }
- (*theMENUPtr) = 0; // termination mark
- ++theMENUPtr;
- SetPermHandleSize((Handle)theMenuHandle, (Size)(theMENUPtr - StripLong((*theMenuHandle))));
-
- HUnlock(CMNUHandle);
- HUnlock((Handle)theMenuHandle);
- return theMenuHandle;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- struct JmpRec
- {
- short opcode;
- pascal void(* target)(short message,
- MenuHandle aMenuHandle,
- Rect& menuRect,
- Point hitPt,
- short& whichItem);
-
- };
-
-
- typedef JmpRec* JmpRecPtr;
-
- pascal void InitUMenuMgr(void)
-
- {
- short num;
- MenuHandle newMenu;
- Handle h;
- short i;
-
- gCmdTable = NULL;
- gMenuTable = NULL;
- pHNullMenuProc = NULL;
-
- // Create the table
- gCmdTable = new TCmdTable;
- gCmdTable->ICmdTable();
-
- // Create the table
- gMenuTable = new TMenuTable;
- gMenuTable->IMenuTable();
-
- // initialize all CMNUs
- num = CountResources('CMNU');
- FailResError();
- for (i = 1; i <= num; ++i)
- {
- Handle CMNUHandle = GetIndResource('CMNU', i);
- FailNILResource(CMNUHandle);
- if (((* (MenuHandle) CMNUHandle)->menuID) > 0) // not in reserved range
- {
- // load the menudef and store it's reference in the menu
- newMenu = ConvertToMenu(CMNUHandle);
- h = GetResource('MDEF', (short)(((long)(*newMenu)->menuProc) >> sizeof(short)));
- (*newMenu)->menuProc = h;
-
- gMenuTable->Insert((Handle) newMenu);
- }
- }
-
- // initialize all MENUs
- num = CountResources('MENU');
- FailResError();
- for (i = 1; i <= num; ++i)
- {
- newMenu = (MenuHandle)GetIndResource('MENU', i);
- FailNILResource((Handle) newMenu);
-
- if (((*newMenu)->menuID) > 0) // not in reserved range
- {
- // load the menudef and store it's reference in the menu
- h = GetResource('MDEF', (short)(((long)(*newMenu)->menuProc) >> sizeof(short)));
- (*newMenu)->menuProc = h;
-
- gMenuTable->Insert((Handle)newMenu);
- }
- }
-
- // Create the null menu proc
- pHNullMenuProc = NewPermHandle(sizeof(JmpRec));
- (*((JmpRecPtr) * pHNullMenuProc)).opcode = 0x4EF9;// JMP
- (*((JmpRecPtr) * pHNullMenuProc)).target = &NullMenuProc;
-
- #if qDebugMsg
- if (cUndo - cEditBase != kSysUndo)
- fprintf(stderr, "Invalid UNDO command number");
- if (cCut - cEditBase != kSysCut)
- fprintf(stderr, "Invalid CUT command number");
- if (cCopy - cEditBase != kSysCopy)
- fprintf(stderr, "Invalid COPY command number");
- if (cPaste - cEditBase != kSysPaste)
- fprintf(stderr, "Invalid PASTE command number");
- if (cClear - cEditBase != kSysClear)
- fprintf(stderr, "Invalid CLEAR command number");
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal Boolean IsManagedMenu(MenuHandle theMenu)
-
- {
- return gMenuTable->GetIdentityItemNo((Handle)theMenu) != kEmptyIndex;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal MenuHandle MAGetMenu(short menuNo)
-
- {
- MenuHandle theMenu = GetMHandle(menuNo); /* do this first ... the menu is likely to be
- in the menubar and more likely of success,
- hence, faster */
-
- if (theMenu == NULL) // Try the menu list
- {
- theMenu = gMenuTable->GetMenu(menuNo);
-
- if (theMenu == NULL) // darn! Try the resource chain
- theMenu = GetResMenu(menuNo);
- }
-
- return theMenu;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- pascal Handle MAGetNewMBar(short menuRsrcID)
-
- {
- MCTableHandle theColorTab;
- Handle itsRsrcHandle;
- SignedByte savedState;
- Handle itsNewMBar;
-
- if (qNeedsColorQD || gConfiguration.hasColorQD)
- theColorTab = GetMCInfo();
-
- // make the 'MBAR' resource non-purgeable, so the Toolbox doesn't die
- itsRsrcHandle = GetResource('MBAR', menuRsrcID);
- if (itsRsrcHandle)
- {
- savedState = HGetState(itsRsrcHandle);
- HNoPurge(itsRsrcHandle);
- }
-
- itsNewMBar = GetNewMBar(menuRsrcID);
-
- // restore the 'MBAR' resource
- if (itsRsrcHandle)
- HSetState(itsRsrcHandle, savedState);
-
- if (theColorTab && (qNeedsColorQD || gConfiguration.hasColorQD))
- {
- HLock((Handle)theColorTab);
- SetMCEntries((short)(GetHandleSize((Handle)theColorTab) / sizeof(MCEntry)), (*theColorTab));
- HUnlock((Handle)theColorTab);
- DispMCInfo(theColorTab);
- }
-
- return itsNewMBar;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void MAInsertMenu(MenuHandle theMenu,
- short beforeID)
-
- {
- MenuCRsrcHandle theColorRsrc;
-
- InsertMenu(theMenu, beforeID);
- /* Since only GetMenu automatically loads the appropriate color information,
- and (sigh) since we can only call GetMenu once, and if you call DeleteMenu
- all the good color stuff goes away (double sigh) we'll have to help out
- the Menu Manager by doing its job for it */
- if (qNeedsColorQD || gConfiguration.hasColorQD)
- {
- theColorRsrc = (MenuCRsrcHandle)GetResource('mctb', (*theMenu)->menuID);
- if (theColorRsrc)
- {
- HLock((Handle)theColorRsrc);
- SetMCEntries((*theColorRsrc)->numEntries, &((*theColorRsrc)->mcEntryRecs[0]));
- HUnlock((Handle)theColorRsrc);
- ReleaseResource((Handle)theColorRsrc);
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void NeedCalcMenuSize(MenuHandle aMenuHandle)
-
- {
- if ((*aMenuHandle)->menuProc == pHNullMenuProc)
- (*aMenuHandle)->menuWidth = 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- /* a null menuProc that is used to inhibit re-calculating the menu's size after each
- call to EnableItem, CheckItem, etc. */
-
- pascal void NullMenuProc(short,
- MenuHandle aMenuHandle,
- Rect& ,
- Point,
- short&)
-
- {
- (*aMenuHandle)->menuWidth = 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- /* If hierarchical the range of IDs for applications is restricted
- See IM V-236. */
- #define kHierarchicalMin 0
- #define kHierarchicalMax 235
-
- typedef Boolean EnableArray[mLastMenu]; // Saved enable flags
- typedef Handle SavePrArray[mLastMenu]; // Saved menu procs
-
- struct SetupStruct
- {
- EnableArray wasEnabled;
- SavePrArray savedProcs;
- };
-
-
- typedef SetupStruct* SetupStructPtr;
-
- Boolean IsSetupMenu(MenuHandle aMenuHandle,
- Boolean isHierarchical)
-
- {
- short menuID = (*aMenuHandle)->menuID;
-
- return (((menuID >= mFirstMenu) && (menuID <= mLastMenu)) // Range of managed menus
- && (menuID != mApple) // _NEVER_ managed!
- && (!isHierarchical // No further restrictions, unless…
- || (isHierarchical && (menuID >= kHierarchicalMin) && (menuID <= kHierarchicalMax))));// must be in valid range for hierarchicals
- }
-
-
- pascal void StartMenuSetup(MenuHandle aMenuHandle,
- Boolean isHierarchical,
- void* staticLink)
- {
- short theCmd;
- short menuID = (*aMenuHandle)->menuID;
-
- if (IsSetupMenu(aMenuHandle, isHierarchical))
- {
- /* Remember the menu itself was enabled, and disable the menu
- and all of its items. */
- ((SetupStructPtr)staticLink)->wasEnabled[menuID] = (Boolean)((*aMenuHandle)->enableFlags & 1);
- (*aMenuHandle)->enableFlags = 0;
-
- // Save the menu's menuproc and set it to the NullMenuProc, so that
- // CalcMenuSize is disabled (will do ÇalcMenuSize at end of setup).
- ((SetupStructPtr)staticLink)->savedProcs[menuID] = (*aMenuHandle)->menuProc;// See comment below
- (*aMenuHandle)->menuProc = pHNullMenuProc;
-
- // Uncheck all items.
- for (short item = 1; item <= CountMItems(aMenuHandle); ++item)// Make sure we don't check items with sub-menus
- {
- GetItemCmd(aMenuHandle, item, theCmd);
- if (theCmd != hMenuCmd)
- CheckItem(aMenuHandle, item, FALSE);// moves/purges memory
- }
- }
- }
-
-
- pascal void EndMenuSetup(MenuHandle aMenuHandle,
- Boolean isHierarchical,
- void* staticLink)
-
- {
- long newFlags;
-
- if (IsSetupMenu(aMenuHandle, isHierarchical))
- {
- newFlags = (*aMenuHandle)->enableFlags;
- // If any items are enabled, enable the menu
- if (newFlags != 0)
- {
- newFlags = (1 | newFlags);
- (*aMenuHandle)->enableFlags = newFlags;
- }
-
- // If the menu's enabled state changed, we have to draw the menu bar.
- if (((newFlags & 1) == 1) != ((SetupStructPtr)staticLink)->wasEnabled[(*aMenuHandle)->menuID])
- InvalidateMenuBar();
-
- // Restore the menuproc.
- (*aMenuHandle)->menuProc = ((SetupStructPtr)staticLink)->savedProcs[(*aMenuHandle)->menuID];
-
- /* menuWidth set to 0 by routines that require CalcMenuSize, by
- calling NeedCalcMenu. */
- if (!(*aMenuHandle)->menuWidth)
- CalcMenuSize(aMenuHandle);
- }
- }
-
-
- pascal void PerformMenuSetup(pascal void(* TheMenuSetterUpper)(void* staticLink),
- void* staticLink)
-
- {
- SetupStruct itsSetupStruct;
-
- EachMenuDo(&StartMenuSetup, &itsSetupStruct);
- TheMenuSetterUpper(staticLink);
- EachMenuDo(&EndMenuSetup, &itsSetupStruct);
-
- if (MenuBarHasPendingUpdate()) // Never executed on system with InvalMenuBar
- {
- DrawMenuBar();
- ValidateMenuBar();
- }
-
- ValidateMenus();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void SetCmdIcon(CmdNumber aCmd,
- Byte menuIcon)
-
- {
- short menu;
- short item;
- MenuHandle aMenuHandle;
-
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... SetCmdIcon(%c%d)", TraceMenuName(aCmd), menuIcon);
- #endif
-
- aMenuHandle = CmdToComponents(aCmd, menu, item);
- if (aMenuHandle)
- SetItemIcon(aMenuHandle, item, menuIcon);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void SetCmdName(CmdNumber aCmd,
- const Str255& menuText)
-
- {
- short menu;
- short item;
- MenuHandle aMenuHandle;
-
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... SetCmdName(%c“%s”)", TraceMenuName(aCmd), (char *) menuText);
- #endif
-
- aMenuHandle = CmdToComponents(aCmd, menu, item);
- if (aMenuHandle)
- SetItem(aMenuHandle, item, menuText);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void SetIndCmdName(CmdNumber aCmd,
- short rsrcID,
- short strIndex)
-
- {
- Str255 s;
-
- GetIndString(s, rsrcID, strIndex);
- SetCmdName(aCmd, s);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void SetMenuState(CmdNumber aCmd,
- short rsrcID,
- short falseBuzzItem,
- short trueBuzzItem,
- Boolean stateVariable)
-
- {
- short buzzItem;
-
- if (stateVariable)
- buzzItem = trueBuzzItem;
- else
- buzzItem = falseBuzzItem;
-
- SetIndCmdName(aCmd, rsrcID, buzzItem);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void SetStyle(CmdNumber aCmd, /* Style */ short aStyle)
-
- {
- short menu;
- short item;
- MenuHandle aMenuHandle;
-
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... SetStyle(%c%d)", TraceMenuName(aCmd), *((Ptr) & aStyle));
- #endif
-
- aMenuHandle = CmdToComponents(aCmd, menu, item);
- if (aMenuHandle)
- SetItemStyle(aMenuHandle, item, aStyle);
- }
-
-
-